package edu.washington.ling.syntric.struct.tree;

import java.util.List;
import java.util.LinkedList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;


public class Node implements Comparable<Node>{
	private Node PSParent;
	private List<Node> PSChildren;
	private HashSet<String> headWords;
	private boolean isTouched;
	private boolean isLCA;
	
	protected Set<String> derrivedFeatures;
	protected Map<String, String> featureMap;
	
	public Node(){
		PSParent = null;
		PSChildren = new LinkedList<Node>();
		headWords = new HashSet<String>();
		isTouched = false;
		isLCA = false;
		derrivedFeatures = new HashSet<String>();
		featureMap = new HashMap<String, String>();
	}
	public Node(Node n) {
		PSParent = null;
		PSChildren = new LinkedList<Node>();
		headWords = new HashSet<String>(n.getHeadWords());
		isTouched = n.isTouched();
		isLCA = n.isLCA();
		derrivedFeatures = new HashSet<String>(n.getDerrivedFeatures());
		featureMap = new HashMap<String, String>(n.getFeatureMap());
		
	}
	public void setPSParent(Node n){
		PSParent = n;
	}
	public void addPSChild(Node n){
		PSChildren.add(n);
	}
	public void addHeadWord(String s){
		headWords.add(s);
	}
	public void addAllHeadWords(String[] strs){
		for (String str: strs) {
			headWords.add(str);
		}
	}
	public void delPSChild(Node n){
		PSChildren.remove(n);
	}
	public void setLabel(String s){
		derrivedFeatures.add("label");
		featureMap.put("label", s);
	}
	public void setFeature(String feat, String val){
		featureMap.put(feat, val);
	}
	public void delFeature(String feat){
		featureMap.remove(feat);
	}
	public void touch(){
		isTouched = true;
	}
	public void unTouch(){
		isTouched = false;
	}
	public void markAsLCA(){
		isLCA = true;
	}
	public void unMarkAsLCA(){
		isLCA = false;
	}
	public boolean hasPSParent() {
		return (PSParent != null);
	}
	public boolean hasLabel() {
		return featureMap.containsKey("label");
	}
	public boolean isDerrived(String feat){
		return derrivedFeatures.contains(feat);
	}
	public boolean hasFeature(String feat){
		return featureMap.containsKey(feat);
	}
	public boolean hasHeadWords(){
		return (headWords.size() > 0);
	}
	public boolean isTouched(){
		return isTouched;
	}
	public boolean isLCA(){
		return isLCA;
	}
	public Node getPSParent(){
		return PSParent;
	}
	public List<Node> getPSChildren(){
		return PSChildren;
	}
	public HashSet<String> getHeadWords(){
		return headWords;
	}
	public String getLabel() {
		return featureMap.get("label");
	}
	public Set<String> getDerrivedFeatures() {
		return derrivedFeatures;
	}
	public Map<String, String> getFeatureMap() {
		return featureMap;
	}
	public Set<String> getFeatures(){
		return featureMap.keySet();
	}
	public String getValue(String feat){
		return featureMap.get(feat);
	}
	public boolean equals(Object other){
		if (this == other){
			return true;
		}
		if (!(other instanceof Node)) {
			return false;
		}
		Node otherNode = (Node) other;
		return (featureMap.equals(otherNode.featureMap));
	}
	public String toString() {
		String basic = "";
		String other = "";
		for (String feat: featureMap.keySet()) {
			if (isDerrived(feat)) {
				basic += String.format("%s=%s ",feat, featureMap.get(feat));
			}
			else {
				other += String.format("%s=%s ",feat, featureMap.get(feat));
			}
		}
		return String.format("Basic: %s; Other: %s", basic, other);
	}
	@Override
	public int hashCode() {
		return featureMap.hashCode();
	}
	@Override
	public int compareTo(Node otherNode) {
		return this.toString().compareTo(otherNode.toString());
	}
}
